#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>

char uid[30],pass[30];
int chk=0,m=20;
char file[20];
struct hash
{
	  char uid[30];
	  char pass[30];
}*a;

void menu();
void main_menu();

int gen_index(int key)                //to generate index value for function1
{
  int i,ind;
  i=0;
	 while(i<m)
	 {
		ind=(key+i)%m;
		if(a[ind].uid[0]=='\0')
		  return ind;
		else
		  i++;
	 }
	 return -1;
}

int rep(int key)
{
  int i,ind; 
  i=0;
	 do
	 {
		ind=(key+i)%m;
		if(a[ind].uid[0]=='\0')
		  break;
		if(strcmp(uid,a[ind].uid)==0)
		  return ind;
		else
		  i++;
	 }while(i<m);
	 return -1;
}

int gen_key(char str[30],char flag)		  //to generate key value for function1
{
	 int key=0,i;
	 for(i=0;i<3;i++)
		key+=(int)str[i];
	 key=key/3;
	 if(flag=='f')
	   return gen_index(key);
	 else
	   return rep(key);
}


int gen_key2(char str[30],char flag)                //to generate key value for function2
{
  int key=0,i;
  key=strlen(str);
  if(flag=='f')
    return gen_index(key);
  else
    return rep(key);
}  

int search_ind3(int key)                             //  //to search index value for function3
{
  int ind,i=0;
  do
  {
    ind=(int)(m*(((float)(key)/4)-(key)/4)+i)%m;
    //if(a[ind].uid[0]=='\0')
    //  break;
    if(strcmp(uid,a[ind].uid)==0)
      return ind;
    else
      i++;
  }while(i<m);
  return -1;
}
  
int gen_ind3(int key)				  //to generate index value for function3
{
  int i=0,ind;
  while(i<m)
  {
    ind=(int)(m*(((float)(key)/4)-(key)/4)+i)%m;
    if(a[ind].uid[0]=='\0')
    {  
      return ind;
    }
    else
      i++;
  }
  return -1;
}
int gen_key3(char str[30],char flag)			  //to generate key value for function3
{
  int key=0,i;
  for(i=0;i<4;i++)
  {
    key+=fabs((int)str[i+1]-(int)str[i]);
  }
  if(flag=='f')
    return gen_ind3(key);
  else
    return search_ind3(key);
}

int search_options(char str[30],int choice,char flag)	//to choose b/w function1 or 2 or 3
{
  int ind;
  switch(choice)
  {
    case 1 :{
              ind=gen_key(str,flag);
	      break;
	    }
    case 2 :{
              ind=gen_key2(str,flag);
	      break;
            }
    case 3 :{
              ind=gen_key3(str,flag);
	      break;
            }
  }
  return ind;
}

void load_uid(int choice)			//to load values from file into a
{
	 int k=-1,ind,i,j;
	 char ch,file_uid[30],file_pass[30];
	 FILE *fp;
	 fp=fopen(file,"r");
	 if(fp==NULL)
	 {
	   puts("FILE DOESN'T EXIST!!!");
	   main_menu();
	 }
	 for(i=0;i<m;i++)
	 {
	   a[i].uid[0]='\0';
	   a[i].pass[0]='\0';
	 }
	 while(!feof(fp))
	 {	
	  fscanf(fp,"%s %s",file_uid,file_pass);
	  ind=search_options(file_uid,choice,'f');
	  if(ind==-1)
	  {
	    a=realloc(a,(m+10)*sizeof(struct hash));
		  m=m+10;
		  load_uid(choice);
		}
		else
		{
		  strcpy(a[ind].uid,file_uid);
		  strcpy(a[ind].pass,file_pass);
		}
		
	 }
	 fclose(fp);
}

    

char check_pass(int choice)				//to check the password at returned index from appropriate function
{
  int ind;
  ind=search_options(uid,choice,'t');
  
  if(ind==-1)
  {
    puts("USERNAME NOT FOUND!!!");
    chk++;
    menu(choice);
  }
  if(strcmp(a[ind].pass,pass)==0)
    return 't';
  else
  { printf("\n%s\t%s",a[ind].pass,pass);
    return 'f';
  }
}


void menu(int choice)			//the search menu 
{
	 int i;
	 char ch='f';
    if(chk<3)
    {
	 printf("\nEnter your Username :");
	 scanf("%s",uid);
	 mark :
	 printf("Enter your Password :");
	 scanf("%s",pass);
	 ch=check_pass(choice);
	 if((ch=='f')&&(chk<2))
	 {
		chk++;
		puts("PASSWORD INCORRECT!!!\nPLEASE TRY AGAIN");
		goto mark;
	 }
	 else
	 if(ch=='t')
	 {
		printf("\nCORRECT PASSWORD\n\n");
		exit(EXIT_SUCCESS);
	 }
	 else
	 if(chk==2)
	 {
		printf("ACCESS DENIED!!!\n\n");
		exit(EXIT_SUCCESS);
	 }
    }
    printf("ACCESS DENIED!!!\n\n");
    exit(EXIT_SUCCESS);
}

void write()				//to write new values into file
{
  char username[30],password[30];
  FILE *fp;
  fp=fopen(file,"a");
  printf("\nEnter your Username :");
  scanf("%s",username);
  printf("Enter your Password :");
  scanf("%s",password);
  fputs("\n",fp);
  fputs(username,fp);	
  fputs("\t",fp);
  fputs(password,fp);
  fclose(fp);
  puts("NEW USER ADDED");
}
void main_menu()		//the main menu
{
  int choice,x;
  FILE *fp,*f;
  mark1 :
  printf("\n\t\tMENU\n\n");
  printf("1.SEARCH\n2.ADD NEW USER\n3.EXIT\nEnter your choice :");
  scanf("%d",&x);
  fp=fopen("data.txt","r");
  if((x==1)||(x==2))
  {
    if(fp==NULL)
  {
    printf("ENTER the filename :");
    scanf("%s",file);
    f=fopen(file,"r");
    if((x==1)&&(f==NULL))
    {
      puts("\nFILE DOESN'T EXIST!!!");
      fclose(f);
      fclose(fp);
      main_menu();
    }
  }
  else
  {
    strcpy(file,"data.txt");
    fclose(fp);
  }
  }
  switch(x)
  {
    case 1:{
             mark2 :
             printf("\n\tENTER THE TYPE OF SEARCH\n");
	     printf("\n1.Linear Search\n2.Length Search\n3.Multiplicative Search\n4.Back\n5.Exit\nEnter Your Choice :");
	     scanf("%d",&choice);
	     if(choice==4)
	       goto mark1;
	     else
	     if(choice==5)
	       exit(EXIT_SUCCESS);
	     else
	       if((choice>=1)&&(choice<=3))
	     {
	       load_uid(choice);
	       menu(choice);
	     }
	     else
	       goto mark2 ;
	     break;
	   }
    case 2: {
	      write();
	      break;
	    }	
    case 3: exit(EXIT_SUCCESS);
    default :goto mark1;
  }
  goto mark1;
}

void main()
{
  a=realloc(a,sizeof(struct hash)*20);		//set size of a to 20
  main_menu();
}